import { defineStore } from 'pinia'
import { ref } from 'vue'

// 文件大小限制：提升到 5GB
const MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024

// IndexedDB 数据库名称和版本
const DB_NAME = 'LogVisionFileData'
const DB_VERSION = 1
const STORE_NAME = 'fileData'

// IndexedDB 辅助函数
async function openFileDataDB(): Promise<IDBDatabase> {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open(DB_NAME, DB_VERSION)
    
    request.onerror = () => reject(request.error)
    request.onsuccess = () => resolve(request.result)
    
    request.onupgradeneeded = (event) => {
      const db = (event.target as IDBOpenDBRequest).result
      if (!db.objectStoreNames.contains(STORE_NAME)) {
        db.createObjectStore(STORE_NAME, { keyPath: 'id' })
      }
    }
  })
}

// 保存大文件到 IndexedDB
async function saveLargeFilesToIndexedDB(fileDataMap: Map<string, string>) {
  try {
    const db = await openFileDataDB()
    const transaction = db.transaction([STORE_NAME], 'readwrite')
    const store = transaction.objectStore(STORE_NAME)
    
    for (const [workspaceId, data] of fileDataMap.entries()) {
      if (data.length >= 1024 * 1024) { // >= 1MB
        await new Promise<void>((resolve, reject) => {
          const request = store.put({ id: workspaceId, data, size: data.length })
          request.onsuccess = () => resolve()
          request.onerror = () => reject(request.error)
        })
        console.log(`大文件已保存到IndexedDB: ${workspaceId}, 大小: ${(data.length / 1024 / 1024).toFixed(2)}MB`)
      }
    }
    
    db.close()
  } catch (error) {
    console.error('保存大文件到IndexedDB失败:', error)
  }
}

// 从 IndexedDB 加载大文件
async function loadLargeFilesFromIndexedDB(): Promise<Map<string, string>> {
  const result = new Map<string, string>()
  
  try {
    console.log('正在打开IndexedDB数据库...')
    const db = await openFileDataDB()
    console.log('IndexedDB数据库打开成功')
    
    const transaction = db.transaction([STORE_NAME], 'readonly')
    const store = transaction.objectStore(STORE_NAME)
    
    console.log('开始从IndexedDB读取数据...')
    const request = store.getAll()
    
    const data = await new Promise<any[]>((resolve, reject) => {
      request.onsuccess = () => {
        console.log('IndexedDB读取成功，数据条数:', request.result.length)
        resolve(request.result)
      }
      request.onerror = () => {
        console.error('IndexedDB读取失败:', request.error)
        reject(request.error)
      }
    })
    
    console.log('开始处理IndexedDB数据...')
    for (const item of data) {
      if (item && item.id && item.data) {
        result.set(item.id, item.data)
        console.log(`IndexedDB数据项: ${item.id}, 大小: ${(item.data.length / 1024 / 1024).toFixed(2)}MB`)
      } else {
        console.warn('IndexedDB数据项格式无效:', item)
      }
    }
    
    db.close()
    console.log('IndexedDB数据库已关闭')
    
  } catch (error) {
    console.error('从IndexedDB加载大文件失败:', error)
    // 如果IndexedDB失败，尝试清理并重新创建
    try {
      console.log('尝试清理损坏的IndexedDB...')
      indexedDB.deleteDatabase(DB_NAME)
      console.log('IndexedDB已清理，下次访问时将重新创建')
    } catch (cleanupError) {
      console.error('清理IndexedDB失败:', cleanupError)
    }
  }
  
  return result
}

export const useFileDataStore = defineStore('fileData', () => {
  // 内存中存储大文件数据
  const fileDataMap = ref<Map<string, string>>(new Map())
  
  // 文件大小记录
  const fileSizeMap = ref<Map<string, number>>(new Map())

  // 初始化时从localStorage和IndexedDB恢复数据
  async function initializeFromStorage() {
    try {
      console.log('=== 开始初始化文件数据存储 ===')
      
      // 1. 从localStorage恢复小文件
      const storedData = localStorage.getItem('fileDataStore')
      const smallFilesMap = new Map()
      const sizeMap = new Map()
      
      if (storedData) {
        try {
          const parsedData = JSON.parse(storedData)
          for (const [key, value] of Object.entries(parsedData)) {
            // 只恢复小文件（小于1MB）
            if (typeof value === 'string' && value.length < 1024 * 1024) {
              smallFilesMap.set(key, value as string)
              sizeMap.set(key, value.length)
              console.log(`从localStorage恢复小文件: ${key}, 大小: ${(value as string).length} 字节`)
            }
          }
        } catch (parseError) {
          console.error('解析localStorage数据失败:', parseError)
          // 清理损坏的数据
          localStorage.removeItem('fileDataStore')
        }
      }
      
      // 2. 从IndexedDB恢复大文件
      console.log('开始从IndexedDB恢复大文件...')
      const largeFilesMap = await loadLargeFilesFromIndexedDB()
      console.log(`从IndexedDB恢复了 ${largeFilesMap.size} 个大文件`)
      
      // 3. 合并小文件和大文件
      const combinedMap = new Map([...smallFilesMap, ...largeFilesMap])
      
      // 4. 更新size map
      for (const [key, data] of largeFilesMap.entries()) {
        sizeMap.set(key, data.length)
        console.log(`大文件已恢复: ${key}, 大小: ${(data.length / 1024 / 1024).toFixed(2)}MB`)
      }
      
      fileDataMap.value = combinedMap
      fileSizeMap.value = sizeMap
      
      console.log(`=== 文件数据存储初始化完成 ===`)
      console.log(`总文件数: ${combinedMap.size}`)
      console.log(`小文件数: ${smallFilesMap.size}`)
      console.log(`大文件数: ${largeFilesMap.size}`)
      console.log(`总内存使用: ${getMemoryUsage().totalSizeMB} MB`)
      
    } catch (error) {
      console.error('从存储恢复文件数据失败:', error)
      // 清理损坏的数据
      localStorage.removeItem('fileDataStore')
      // 重置状态
      fileDataMap.value = new Map()
      fileSizeMap.value = new Map()
    }
  }

  // 保存到localStorage（小文件）和IndexedDB（大文件）
  async function saveToStorage() {
    try {
      // 1. 保存小文件到localStorage
      const dataToStore: Record<string, string> = {}
      fileDataMap.value.forEach((value, key) => {
        // 只保存小于1MB的文件到localStorage
        if (value.length < 1024 * 1024) {
          dataToStore[key] = value
        }
      })
      localStorage.setItem('fileDataStore', JSON.stringify(dataToStore))
      console.log('小文件数据已保存到localStorage')
      
      // 2. 保存大文件到IndexedDB
      await saveLargeFilesToIndexedDB(fileDataMap.value)
      console.log('大文件数据已保存到IndexedDB')
      
    } catch (error) {
      console.error('保存文件数据失败:', error)
    }
  }

  // 方法
  async function setFileData(workspaceId: string, data: string) {
    try {
      console.log(`=== setFileData 调用 ===`)
      console.log(`工作区ID: ${workspaceId}`)
      console.log(`数据长度: ${data.length}`)
      console.log(`数据预览: ${data.substring(0, 100)}...`)
      
      if (data.length > MAX_FILE_SIZE) {
        console.warn(`文件非常大 (${(data.length / 1024 / 1024).toFixed(2)}MB)，请注意内存占用`)
      }

      // 直接保存完整数据到内存
      fileDataMap.value.set(workspaceId, data)
      fileSizeMap.value.set(workspaceId, data.length)
      console.log(`文件数据已保存到内存，工作区ID: ${workspaceId}，大小: ${(data.length / 1024 / 1024).toFixed(2)}MB`)
      
      console.log(`当前内存中的工作区数量: ${fileDataMap.value.size}`)
      console.log(`当前内存使用情况: ${getMemoryUsage().totalSizeMB} MB`)
      
      // 异步保存到持久化存储
      await saveToStorage()
    } catch (error) {
      console.error('设置文件数据失败:', error)
      throw error
    }
  }

  function getFileData(workspaceId: string): string | undefined {
    console.log(`=== getFileData 调用 ===`)
    console.log(`请求工作区ID: ${workspaceId}`)
    console.log(`当前内存中的工作区: ${Array.from(fileDataMap.value.keys())}`)
    
    const data = fileDataMap.value.get(workspaceId)
    if (data) {
      console.log(`找到数据，长度: ${data.length}`)
      console.log(`数据预览: ${data.substring(0, 100)}...`)
    } else {
      console.log(`未找到数据`)
    }
    
    return data
  }

  function hasFileData(workspaceId: string): boolean {
    return fileDataMap.value.has(workspaceId)
  }

  function getFileSize(workspaceId: string): number {
    return fileSizeMap.value.get(workspaceId) || 0
  }

  async function removeFileData(workspaceId: string) {
    fileDataMap.value.delete(workspaceId)
    fileSizeMap.value.delete(workspaceId)
    console.log(`文件数据已从内存中删除，工作区ID: ${workspaceId}`)
    await saveToStorage()
  }

  async function clearAllFileData() {
    fileDataMap.value.clear()
    fileSizeMap.value.clear()
    console.log('所有文件数据已从内存中清除')
    await saveToStorage()
  }

  // 获取内存使用情况
  function getMemoryUsage() {
    let totalSize = 0
    fileSizeMap.value.forEach(size => {
      totalSize += size
    })
    return {
      totalSize,
      totalSizeMB: (totalSize / 1024 / 1024).toFixed(2),
      workspaceCount: fileDataMap.value.size
    }
  }

  return {
    setFileData,
    getFileData,
    hasFileData,
    removeFileData,
    clearAllFileData,
    getFileSize,
    getMemoryUsage,
    initializeFromStorage
  }
}) 